import queue
import json
import keyboard
from queue import Queue
from pathlib import Path
from typing import Dict,List
from PySide2.QtWidgets import QWidget,QVBoxLayout,QFileDialog
from PySide2.QtCore import Qt,Signal
from widget.ui_mainCentralwidget import Ui_main_centralwidget

from widget.dataInfoListWidget import DataInfoListWidget
from taskCilick.runClickThread import RunClickThread
from taskCilick.runClickThreadType import RunClickThreadType
from taskCilick.runClickThreadStatus import RunClickThreadStatus
from widget.clickPosi import ClickPosi
from appConfig.appConfig import SharedAppConfig

class MainCentralWidget(QWidget):

    SigMessage = Signal(str)
    SigFindPosi = Signal(bool)

    FiledAllLoopCount = 'allLoopCount'
    FiledLoopCount = 'loopCount'
    FiledBeginPositionList = 'beginPositionList'
    FiledLoopPositionList = 'loopPositionList'
    FiledEndedPositionList = 'endedPositionList'

    def __init__(self, parent: QWidget = None, flags: Qt.WindowFlags = Qt.WindowFlags()) -> None:
        super().__init__(parent, flags)

        self.ui = Ui_main_centralwidget()
        self.ui.setupUi(self)

        self.task_queue = Queue(100)
        self.run_click_th = RunClickThread(self.task_queue, self)
        self.run_click_th.SigMessage.connect(self.SigMessage)
        self.run_click_th.SigTaskDone.connect(self.run_loop_done)
        self.run_click_th.SigAllLoopProgressValue.connect(self.ui.progressBar.setValue)
        self.run_click_th.SigLoopProgressValue.connect(self.ui.progressBar_loop.setValue)
        self.run_click_th.SigRunTimeTotal.connect(self.update_lable_runtime_total)

        self.ui.groupBox_loop_begin.setLayout(QVBoxLayout())
        # self.ui.groupBox_looping.setLayout(QVBoxLayout())
        self.ui.groupBox_loop_end.setLayout(QVBoxLayout())

        self.begin_data_widget = DataInfoListWidget(self)
        self.loop_data_widget = DataInfoListWidget(self)
        self.ended_data_widget = DataInfoListWidget(self)

        self.begin_data_widget.SigMessage.connect(self.SigMessage)
        self.begin_data_widget.SigFindPosi.connect(self.SigFindPosi)
        self.loop_data_widget.SigMessage.connect(self.SigMessage)
        self.loop_data_widget.SigFindPosi.connect(self.SigFindPosi)
        self.ended_data_widget.SigMessage.connect(self.SigMessage)
        self.ended_data_widget.SigFindPosi.connect(self.SigFindPosi)

        self.ui.groupBox_loop_begin.layout().addWidget(self.begin_data_widget)
        self.ui.groupBox_looping.layout().addWidget(self.loop_data_widget)
        self.ui.groupBox_loop_end.layout().addWidget(self.ended_data_widget)

        self.ui.pushButton_start.clicked.connect(self.but_start_click)
        self.ui.pushButton_re_start.clicked.connect(self.task_restart)
        self.ui.pushButton_config_load.clicked.connect(self.but_config_load_clicked)
        self.ui.pushButton_config_save.clicked.connect(self.config_save)
        self.ui.pushButton_config_save_as.clicked.connect(self.but_config_save_as_clicked)
        self.run_click_th.start()

        self.config_file = Path('config_posi.json')

        keyboard.add_hotkey('ctrl+q', self.task_pause)
        keyboard.add_hotkey('ctrl+d', self.test)
        self.config_load()
        self.w = ClickPosi()
    
    def test(self):

        
        self.w.exec_()
        # self.w.deleteLater()
        # print(1)

    def close_clear(self) -> None:
        if not self.run_click_th.isFinished():
            self.run_click_th.requestInterruption()
            while not self.run_click_th.isFinished():
                pass

    def get_all_data_info(self) -> Dict:

        data = {}
        data.setdefault(self.FiledAllLoopCount, self.ui.spinBox_all_loop_count.value())
        data.setdefault(self.FiledLoopCount, self.ui.spinBox_loop_count.value())
        data.setdefault(self.FiledBeginPositionList, self.begin_data_widget.data_info_list())
        data.setdefault(self.FiledLoopPositionList, self.loop_data_widget.data_info_list())
        data.setdefault(self.FiledEndedPositionList, self.ended_data_widget.data_info_list())
        return data
    
    def config_load(self):

        if not self.config_file.exists():
            self.SigMessage.emit('配置文件加载失败!')
            return
        
        self.ui.label_config_name.setText(self.config_file.name)
        self.ui.label_config_name.setToolTip(str(self.config_file))

        try:
            with self.config_file.open('r') as f:
                data = json.load(f)
                self.ui.spinBox_all_loop_count.setValue(data[self.FiledAllLoopCount])
                self.ui.spinBox_loop_count.setValue(data[self.FiledLoopCount])
                self.begin_data_widget.clear_data_info_widget()
                self.loop_data_widget.clear_data_info_widget()
                self.ended_data_widget.clear_data_info_widget()
                self.begin_data_widget.add_data_info_widgets(data[self.FiledBeginPositionList])
                self.loop_data_widget.add_data_info_widgets(data[self.FiledLoopPositionList])
                self.ended_data_widget.add_data_info_widgets(data[self.FiledEndedPositionList])
        except Exception as err:
            self.SigMessage.emit(f'配置文件加载失败![{err}]')
            return
    
    def config_save(self):

        with self.config_file.open('w') as f:
            json.dump(self.get_all_data_info(), f, indent=4)
        self.SigMessage.emit('配置文件保存成功!')
    
    def but_config_load_clicked(self):

        file,_ = QFileDialog.getOpenFileName(self, '选择配置文件', str(SharedAppConfig.OPEN_FILE_DIR), '*.json')
        if file == '': return
        file = Path(file)
        SharedAppConfig.OPEN_FILE_DIR = file.parent
        self.config_file = file
        self.config_load()

    def but_config_save_as_clicked(self):

        file,_ = QFileDialog.getSaveFileName(self, '选择配置文件', str(SharedAppConfig.OPEN_FILE_DIR), '*.json')
        if file == '': return
        file = Path(file)
        SharedAppConfig.OPEN_FILE_DIR = file.parent
        self.config_file = file
        self.config_save()
        self.config_load()

    def task_pause(self):
        
        if self.ui.pushButton_start.property(RunClickThreadType.NAME) == RunClickThreadType.PAUSE:
            self.task_start()
            self.SigMessage.emit('任务已继续进行!')
            self.task_queue.put(RunClickThreadType.CONTINUE)
            return
        self.task_queue.put(RunClickThreadType.PAUSE)
        self.ui.pushButton_start.setProperty(RunClickThreadType.NAME, RunClickThreadType.PAUSE)
        self.ui.pushButton_start.setText('开始')

    def task_start(self):

        self.ui.pushButton_start.setText('暂停')
        self.ui.pushButton_start.setProperty(RunClickThreadType.NAME, RunClickThreadType.START)

    def task_restart(self):

        try:
            self.task_queue.put(RunClickThreadType.START)
            self.task_start()
            self.ui.progressBar.reset()
        except queue.Full:
            pass
    
    def but_start_click(self):

        if self.run_click_th.run_status == RunClickThreadStatus.PAUSE:
            self.task_pause()
            return
        self.task_restart()

    def run_loop_done(self):

        self.ui.pushButton_start.setText('开始')

    def update_lable_runtime_total(self, v:float):

        h = v // 3600
        m = (v - h * 3600) // 60
        s = int(v % 60)
        if h > 0:
            text = f'{h}时{m}分{s}秒'
        elif m > 0:
            text = f'{m}分{s}秒'
        else:
            text = f'{s}秒'
        self.ui.label_run_total_time.setText(text)